package com.qp.basics.estivate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 有点类似hibernate的SessionFactory，但包含了表结构的操作。
 * 
 * 我考虑再三，尝试了一次次，最后感觉还是把Table和Column作为POJO。 实现上的差异性只体现在Database类上。
 * 不过我不会cglib，所以我还是手工在Table和Column里加入上上级的Database和Table。
 * 
 * 现在表结果的操作还是放在Database里了，而数据的操作放到Session对象和Query对象里了。
 * 创建和根据主键的修改和删除的操作放在Session里。 另外Session里的一些sql操作是生成一个Query来实现的。
 * 
 */
public interface Database {
	Map<String, String> databaseImpls = new HashMap();

	String getDatabaseType();

	/**
	 * 列举本数据库支持的数据类型。
	 * 
	 * @return
	 */
	String[] getDataTypes();

	/**
	 * 清空缓存的数据库结构。
	 */
	void reset();

	String getDatabaseName();

	void setDatabaseName(String databaseName);

	/**
	 * 对于mysql等就是数据库名称，对于oracle就是用户名。
	 * 
	 * @return
	 */
	String getTableSchema();

	void setTableSchema(String tableSchema);

	/**
	 * 数据库描述信息
	 * 
	 * @return
	 */
	String getDescription();

	void setDescription(String description);

	/**
	 * mysql返回`，sqlserver返回[,oracle返回"。
	 * mysql使用``来包装关键字，sqlserver使用[],oracle使用""。
	 * 
	 * @return
	 */
	String getPreFix();

	/**
	 * mysql返回`，sqlserver返回],oracle返回"。
	 * mysql使用``来包装关键字，sqlserver使用[],oracle使用""。
	 * 
	 * @return
	 */
	String getPostFix();

	/**
	 * 通过ConnectionProvider可以获取Connection。
	 * 
	 * @return
	 */
	ConnectionProvider getConnectionProvider();

	void setConnectionProvider(ConnectionProvider connectionProvider);

	/**
	 * 获取指定表的字段列表。
	 * 
	 * @param table
	 * @return
	 */
	Column[] getColumns(Table table);

	/**
	 * 修改字段的属性。
	 * 
	 * @param column
	 */
	void alterColumn(Table table, String oldColumnName, Column newColumn);

	/**
	 * 新增字段。
	 * 
	 * @param column
	 */
	void addColumn(Table table, Column column);

	/**
	 * 删除字段。
	 * 
	 * @param table
	 * @param column
	 */
	void dropColumn(Table table, Column column);

	/**
	 * 重设主键。
	 * 
	 * @param table
	 * @param pks
	 */
	void resetPrimaryKey(Table table, Column[] pks);

	/**
	 * 将获取的表添加约束
	 * 
	 * @return
	 */
	Table[] addCheckConstraints(Table[] tables);

	/**
	 * 获取所有的表。 注意这里使用了缓存。
	 * 
	 * @return
	 */
	Table[] getTables();

	/**
	 * 根据表名获取表对象。
	 * 
	 * @param tableName
	 * @return
	 */
	Table getTable(String tableName);

	/**
	 * 其实做不到一个表对象，传递到任一个Database实现上， 然后创建对应的表，因为Column对象里的数据并不对应。
	 * 如果在Mysql中有张表，你想在Oracle里重建一个，那么你需要 进行处理将Column中的各种定义做修改，尤其是数据类型。
	 * 本方法的实现，我现在采用的是先获取sql语句，然后执行之。
	 * 
	 * @param table
	 * @return
	 */
	void createTable(Table table);

	/**
	 * 删除表。
	 * 
	 * @param tableName
	 */
	void dropTable(String tableName);

	/**
	 * 获取建表语句。 目前几个实现还都比较简单。
	 * 
	 * @param table
	 * @return
	 */
	String getTableCreateSql(Table table);

	/**
	 * 修改表注释。
	 * 
	 * @param tableName
	 * @param comment
	 */
	void alterTableComment(String tableName, String comment);

	/**
	 * 修改表名。
	 * 
	 * @param oldTableName
	 * @param tableName
	 */
	void alterTableName(String oldTableName, String tableName);

	/**
	 * 新打开一个Session。
	 * 
	 * @return
	 */
	Session openSession();

	/**
	 * 备份数据库。
	 * 
	 * @param exportType
	 *            备份方式，如oracle可以备份为dmp格式，还可以备份为sql格式。
	 * @param exportTo
	 *            备份文件的存储路径。当然这里设计为输出流更为通用。
	 */
	void exportDatabase(String exportType, String exportTo);

	/**
	 * 还原数据库。
	 * 
	 * @param importType
	 * @param importFrom
	 */
	void importDatabase(String importType, String importFrom);

	/**
	 * 获取数据类型转换器。
	 * 
	 * @return
	 */
	DataTypeConvertor getDataTypeConvertor();

	void addForeignKeys(Database db, Table fkTable);

	List<Table> getNoPKTables();

	List<Column> getNoIndexForeignColumns();

	String getVersion();

	void setVersion(String version);

	/*-----------对View的操作---------------*/
	/**
	 * 获取所有的用户视图
	 */
	List<View> getUserViews();

	/**
	 * 获取创建视图的语句
	 * 
	 * @param name
	 * @return
	 */
	String getViewTextByName(String name);
	
	/**
	 * Retrieve available databases
	 * @return
	 */
	public List<Database> getAvailableDatabases();
}
